package cn.com.aiouyi.entity;

import java.io.Serializable;
import java.util.Date;
import java.util.Objects;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.validation.groups.Default;

import org.hibernate.annotations.Where;

import cn.com.aiouyi.listener.EntityListener;
import lombok.Getter;
import lombok.Setter;

/**
 * Entity - 基类
 * @author hanson
 */
@EntityListeners(EntityListener.class)
@MappedSuperclass
@Getter
@Setter
public abstract class BaseEntity<ID extends Serializable> implements Serializable {

	private static final long serialVersionUID = -7103197793672462521L;

	/** "ID"属性名称 */
	public static final String ID_PROPERTY_NAME = "id";

	/** "创建日期"属性名称 */
	public static final String CREATE_DATE_PROPERTY_NAME = "createDate";

	/** "修改日期"属性名称 */
	public static final String MODIFY_DATE_PROPERTY_NAME = "modifyDate";

	/** "版本"属性名称 */
	public static final String VERSION_PROPERTY_NAME = "version";

	/**
	 * 保存验证组
	 */
	public interface Save extends Default {

	}

	/**
	 * 更新验证组
	 */
	public interface Update extends Default {

	}

	/** ID */
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(unique = true, nullable = false)
	private ID id;

	/** 创建日期 */
	@Column(nullable = false, updatable = false)
	private Date createDate;

	/** 修改日期 */
	@Column(nullable = false)
	private Date modifyDate;

	/** 版本 */
	@Version
	@Column(nullable = false)
	private Long version;
	
	/** 是否已被删除 */
	@Column(columnDefinition="bit default false")
	@Where(clause = "deleted = 0")
	private Boolean isDeleted;
	
	/** 删除日期 */
	private Date deleteDate;

	/**
	 * 判断是否为新建对象
	 * @return 是否为新建对象
	 */
	@Transient
	public boolean isNew() {
		return getId() == null;
	}

	@Override
	public String toString() {
		return String.format("Entity of type %s with id: %s", getClass().getName(), getId());
	}
	
	/**
	 * 重写equals方法
	 * @param obj 对象
	 * @return 是否相等
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj == null) { 
			return false;
		}
		if (this == obj) {
			return true;
		}
		if (!BaseEntity.class.isAssignableFrom(obj.getClass())) {
			return false;
		}
		BaseEntity<?> other = (BaseEntity<?>) obj;
		return getId() != null ? getId().equals(other.getId()) : false;
	}
    
	/**
	 * 重写hashCode方法
	 * @return HashCode
	 */
	@Override
	public int hashCode() {
		/* 经典写法
		 * int hashCode = 17;
		hashCode += getId() != null ? getId().hashCode() * 31 : 0;
		return hashCode;
		*/
		// 工具类写法，底层其实跟上面一样
		return Objects.hash(getId());
	}

	/**
	 * 初始化
	 */
	public BaseEntity(){
		Date now = new Date(); 
		this.createDate = now;
		this.modifyDate = now;
		this.isDeleted = false;
	}

}
